#include <stdlib.h>
#include <string.h>
#include "keyfile.h"
#include "ofp_config.h"
#include "common.h"
#include "ccm4201s.h"


ofp_upgrade_mode_info g_upgrade_mode_info[UPGRADE_MODE_MAX] = {
    {
        .mode = FORCE_UPGRADE,
        .mode_sring =OFP_KEY_VALUE_FORCE_UPGRADE_MODE,
        .description = "Force upgrade without checking the version",
    },
    {
        .mode = DONT_UPGRADE,
        .mode_sring =OFP_KEY_VALUE_DONT_UPGRADE_MODE,
        .description = "Dont upgrade",
    },
    {
        .mode = AUTO_UPGRADE,
        .mode_sring =OFP_KEY_VALUE_AUTO_UPGRADE_MODE,
        .description = "If the version is different, upgrade",
    },
    {
        .mode = SMART_UPGRADE,
        .mode_sring =OFP_KEY_VALUE_SMART_UPGRADE_MODE,
        .description = "If the new version is determined to be higher than the actual version, then upgrade",
    },
};

const ofp_mcu_drv_info g_mcu_drv_info[DEVICE_MAX] = {
    {
        .mcu_name = CCM4201S_CPU_NAME,
        .mcu_type =DEVICE_CCM4201S,
        .bus_type =USB_TYPE,
        .mcu_upgrade_fun = ccm4201s_usb_upgrade,
    },
};

static int32_t ofp_read_drv_config_file(GKeyFile *file, ofp_drv_conf_key_value_param *param)
{
    ofp_drv_conf_key_device_param_group *dpg = &(param->device_param_group);
    ofp_drv_conf_key_upgrade_param_group *upg = &(param->upgrade_param_group);
    ofp_drv_conf_key_driver_param_group *drpg = &(param->driver_param_group);

    OFP_LOGD("ofp_read_drv_config_file =====================>enter\n");

    if (file == NULL) {
        OFP_LOGE("ofp_read_drv_config_file =====================>error exit\n");
        return -1;
    }
    dpg->mcu_name = ofp_key_file_get_string(file, OFP_GROUP_CONF_DEVICE_PARAM, OFP_KEY_CONF_MCU_NAME);
    dpg->bus_type = ofp_key_file_get_string(file, OFP_GROUP_CONF_DEVICE_PARAM, OFP_KEY_CONF_BUS_TYPE);
    dpg->usb_vid = ofp_key_file_get_string(file, OFP_GROUP_CONF_DEVICE_PARAM, OFP_KEY_CONF_USB_VID);

    upg->firmware_name = ofp_key_file_get_string(file, OFP_GROUP_CONF_UPGRADE_PARAM, OFP_KEY_CONF_FIRMWARE_NAME);
    upg->firmware_version = ofp_key_file_get_string(file, OFP_GROUP_CONF_UPGRADE_PARAM, OFP_KEY_CONF_FIRMWARE_VERSION);
    upg->need_upgrade_flag = ofp_key_file_get_integer(file, OFP_GROUP_CONF_UPGRADE_PARAM, OFP_KEY_CONF_NEED_UPGRADE_FLAG);
    upg->upgrade_mode = ofp_key_file_get_string(file, OFP_GROUP_CONF_UPGRADE_PARAM, OFP_KEY_CONF_UPGRADE_MODE);
    upg->boot_usb_vid = ofp_key_file_get_string(file, OFP_GROUP_CONF_UPGRADE_PARAM, OFP_KEY_CONF_USB_BOOT_VID);


    drpg->driver_name = ofp_key_file_get_string(file, OFP_GROUP_CONF_DRIVER_PARAM, OFP_KEY_CONF_DRIVER_NAME);
    drpg->enroll_times = ofp_key_file_get_integer(file, OFP_GROUP_CONF_DRIVER_PARAM, OFP_KEY_CONF_ENROLL_TIMES);
    drpg->enroll_min_id = ofp_key_file_get_integer(file, OFP_GROUP_CONF_DRIVER_PARAM, OFP_KEY_CONF_ENROLL_MIN_ID);
    drpg->enroll_max_id = ofp_key_file_get_integer(file, OFP_GROUP_CONF_DRIVER_PARAM, OFP_KEY_CONF_ENROLL_MAX_ID);
    drpg->system_name = ofp_key_file_get_string(file, OFP_GROUP_CONF_DRIVER_PARAM, OFP_KEY_CONF_SYSTEM_NAME);
    drpg->enroll_timeout = ofp_key_file_get_integer(file, OFP_GROUP_CONF_DRIVER_PARAM, OFP_KEY_CONF_ENROLL_TIMEOUT);
    drpg->log_level = ofp_key_file_get_integer(file, OFP_GROUP_CONF_DRIVER_PARAM, OFP_KEY_CONF_LOG_LEVEL);

    OFP_LOGD("ofp_read_drv_config_file =====================>exit\n");
    return 0;
}


static void ofp_dev_get_drv_config_string_param(char *dest, char *source)
{
    char dump_null[5]="NULL";

    if (source != NULL) {
        memcpy(dest, source, strlen(source) + 1);
        g_free(source);
        source = NULL;
    } else {
        memcpy(dest, dump_null, strlen(dump_null) + 1);
    }
}

static void ofp_dev_get_drv_config_uint16_param(uint16_t *dest, char *source)
{
    char dump_null[5]="NULL";

    if (source != NULL) {
        *dest = ((uint16_t)(strtoul(source, NULL, 16))); //转化为verdor id
        g_free(source);
        source = NULL;
    } else {
        *dest = 0u;
    }
}

static void ofp_dev_get_drv_config_mcu_param(ofp_drv_device_param_conf *dpc, uint8_t *mcu_name)
{
    int32_t ret = 0;
    int32_t i = 0;
    int32_t count;
    if (mcu_name != NULL) {
        count = sizeof(g_mcu_drv_info)/sizeof(g_mcu_drv_info[0]);

        for (i = 0; i < count; i++) {
            ret = memcmp(mcu_name, g_mcu_drv_info[i].mcu_name, strlen(g_mcu_drv_info[i].mcu_name));
            if (ret == 0) {
                dpc->mcu_type = g_mcu_drv_info[i].mcu_type;
                memcpy(dpc->mcu_name, g_mcu_drv_info[i].mcu_name, strlen(g_mcu_drv_info[i].mcu_name));
                break;
            }
        }
        g_free(mcu_name);
        mcu_name = NULL;
    } else {
        dpc->mcu_type = DEVICE_MAX;
    }
}

static void ofp_dev_get_drv_config_upgrade_mode(ofp_drv_upgrade_param_conf *upc, uint8_t *upgrade_mode)
{
    int32_t ret = 0;
    int32_t i = 0;
    int32_t count;
    if (upgrade_mode != NULL) {
        count = sizeof(g_upgrade_mode_info)/sizeof(g_upgrade_mode_info[0]);
        for (i = 0; i < count; i++) {
            ret = memcmp(upgrade_mode, g_upgrade_mode_info[i].mode_sring, strlen(g_upgrade_mode_info[i].mode_sring));
            if (ret == 0) {
                upc->upgrade_mode = g_upgrade_mode_info[i].mode;
                break;
            }
        }
        g_free(upgrade_mode);
        upgrade_mode = NULL;
    } else {
        upc->upgrade_mode = DONT_UPGRADE;
    }
}

static void ofp_dev_get_drv_config_bus_type(ofp_drv_device_param_conf *dpc, uint8_t *bus_type)
{
    if (bus_type == NULL) {
        OFP_LOGE("ofp_dev_get_drv_config_bus_type param error \n");
        dpc->bus_type = BUS_TYPE_MAX;
        return;
    }
    // USB为字符串长度为3
    if (memcmp(bus_type, "USB", 3) == 0) {
        dpc->bus_type = USB_TYPE;
        goto FREE;
    }
    // UART为字符串长度为4
    if (memcmp(bus_type, "UART", 4) == 0) {
        dpc->bus_type = UART_TYPE;
        goto FREE;
    }
    dpc->bus_type = BUS_TYPE_MAX;

FREE:
    g_free(bus_type);
    bus_type = NULL;
}

static void ofp_dev_get_drv_config_os_type(ofp_drv_driver_param_conf *drpc, uint8_t *os_type)
{
    if (os_type == NULL) {
        OFP_LOGE("ofp_dev_get_drv_config_os_type param error \n");
        drpc->system_id = FP_NONE_OS_TYPE;
        return;
    }

    if (memcmp(os_type, OFP_KEY_VALUE_KYLIN_SYSTEM, 5) == 0) {
        drpc->system_id = FP_KYLIN_OS_TYPE;
        goto FREE;
    }
    // UART为字符串长度为4
    if (memcmp(os_type, OFP_KEY_VALUE_UOS_SYSTEM, 3) == 0) {
        drpc->system_id = FP_UOS_OS_TYPE;
        goto FREE;
    }

    if (memcmp(os_type, OFP_KEY_VALUE_NFS_SYSTEM, 3) == 0) {
        drpc->system_id = FP_NFS_OS_TYPE;
        goto FREE;
    }

    drpc->system_id = FP_NONE_OS_TYPE;

FREE:
    g_free(os_type);
    os_type = NULL;
}


static void ofp_dev_get_drv_config_param(ofp_drv_conf *drv_cfg, ofp_drv_conf_key_value_param *param)
{
    ofp_drv_conf_key_device_param_group *dpg = &(param->device_param_group);
    ofp_drv_conf_key_upgrade_param_group *upg = &(param->upgrade_param_group);
    ofp_drv_conf_key_driver_param_group *drpg = &(param->driver_param_group);


    ofp_drv_device_param_conf *dpc = &(drv_cfg->device_param_conf);
    ofp_drv_upgrade_param_conf *upc = &(drv_cfg->upgrade_param_conf);
    ofp_drv_driver_param_conf *drpc = &(drv_cfg->driver_param_conf);

    ofp_dev_get_drv_config_mcu_param(dpc, dpg->mcu_name);
    ofp_dev_get_drv_config_uint16_param(&(dpc->usb_vid), dpg->usb_vid);
    ofp_dev_get_drv_config_bus_type(dpc, dpg->bus_type);

    ofp_dev_get_drv_config_string_param(upc->firmware_name, upg->firmware_name);
    ofp_dev_get_drv_config_string_param(upc->firmware_version, upg->firmware_version);
    upc->need_upgrade_flag = upg->need_upgrade_flag;
    ofp_dev_get_drv_config_upgrade_mode(upc, upg->upgrade_mode);
    ofp_dev_get_drv_config_uint16_param(&(upc->boot_usb_vid), upg->boot_usb_vid);

    ofp_dev_get_drv_config_string_param(drpc->driver_name, drpg->driver_name);
    drpc->enroll_times = drpg->enroll_times;
    drpc->enroll_min_id = drpg->enroll_min_id;
    drpc->enroll_max_id = drpg->enroll_max_id;
    ofp_dev_get_drv_config_os_type(drpc, drpg->system_name);
    drpc->enroll_timeout = drpg->enroll_timeout;
    drpc->log_level = drpg->log_level;
}
int32_t ofp_dev_open_drv_config(ofp_drv_conf *drv_cfg, uint8_t *file_name)
{
    int32_t ret = 0;
    ret = ofp_key_file_open(&(drv_cfg->drv_cfg_file), file_name);
    if (ret != 0) {
        OFP_LOGE("ofp_dev_open_drv_config : %s  error\n", file_name);
    }
    return ret;
}

int32_t ofp_dev_get_drv_config(ofp_drv_conf *drv_cfg)
{
    ofp_drv_conf_key_value_param key_value_param;
    ofp_drv_device_param_conf *dpc = &(drv_cfg->device_param_conf);
    ofp_drv_upgrade_param_conf *upc = &(drv_cfg->upgrade_param_conf);
    ofp_drv_driver_param_conf *drpc = &(drv_cfg->driver_param_conf);
    int32_t ret = 0;

    OFP_LOGD("ofp_dev_get_drv_config =====================>enter\n");

    ret = ofp_read_drv_config_file(drv_cfg->drv_cfg_file, &key_value_param);
    if (ret < 0) {
        OFP_LOGE("ofp_read_drv_config_file error code:%d \n", ret);
        return -1;
    }

    ofp_dev_get_drv_config_param(drv_cfg, &key_value_param);

    OFP_LOGI("mcu name: %s \n", dpc->mcu_name);
    OFP_LOGI("vendor id: 0x%04x \n", dpc->usb_vid);
    OFP_LOGI("mcu type: %d \n", dpc->mcu_type);
    OFP_LOGI("bus type: %d \n", dpc->bus_type);


    OFP_LOGI("need upgrade flag: %d \n", upc->need_upgrade_flag);
    OFP_LOGI("upgrade mode: %d \n", upc->upgrade_mode);
    OFP_LOGI("boot vendor_id: 0x%04x \n", upc->boot_usb_vid);
    OFP_LOGI("firmware name: %s \n", upc->firmware_name);
    OFP_LOGI("firmware version : %s \n", upc->firmware_version);


    OFP_LOGI("fp enroll times: %d \n", drpc->enroll_times);
    OFP_LOGI("fp enroll min id: %d \n", drpc->enroll_min_id);
    OFP_LOGI("fp enroll max id: %d \n", drpc->enroll_max_id);
    OFP_LOGI("system id: %d \n", drpc->system_id);
    OFP_LOGI("fp enroll timeout : %d \n", drpc->enroll_timeout);
    OFP_LOGI("log level : %d \n", drpc->log_level);

    OFP_LOGD("ofp_dev_get_drv_config =====================>exit\n");
    return 0;
}

int32_t ofp_dev_set_drv_upgrade_flag(ofp_drv_conf *drv_cfg, int32_t value)
{
    int32_t ret = 0;
    ret = ofp_key_file_set_and_save_integer(drv_cfg->drv_cfg_file, OFP_DRIVER_CONFIG_FILE,
        OFP_GROUP_CONF_UPGRADE_PARAM, OFP_KEY_CONF_NEED_UPGRADE_FLAG, value);
    if (ret < 0) {
        OFP_LOGE("ofp_dev_set_drv_upgrade_flag error code:%d \n", ret);
        return -1;
    }
    return 0;

}

void ofp_dev_close_drv_config(ofp_drv_conf *drv_cfg)
{
    ofp_key_file_close(drv_cfg->drv_cfg_file);
}

